package cn.zf233.xcloud.util;

import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * Created by zf233 on 2020/11/27
 * Redis 工具类
 * 文件缓存 & KV操作等
 */
@Component
public class RedisUtil {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private RedisTemplate<String, Long> longRedisTemplate;

    @Resource
    private RedisTemplate<String, byte[]> redisTemplateOfFileCache;

    public Set<String> keys(String keyword) {
        return stringRedisTemplate.keys(keyword);
    }

    // String K/V operation
    public void set(String key, String value) {
        ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
        ops.set(key, value);
    }

    public void set(String key, String value, Long timeOut) {
        ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
        ops.set(key, value, timeOut, TimeUnit.SECONDS);
    }

    public String get(String key) {
        ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
        return ops.get(key);
    }

    public Long ttl(String key) {
        return stringRedisTemplate.getExpire(key);
    }

    public void remove(String key) {
        stringRedisTemplate.delete(key);
    }

    public Boolean exists(String key) {
        return stringRedisTemplate.hasKey(key);
    }

    public Long increment(String key) {
        ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
        return ops.increment(key);
    }

    public Long increment(String key, Long size) {
        ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
        return ops.increment(key, size);
    }

    // String K/V operation

    // Set K/V operation
    public void setAdd(String setKey, Long value) {
        SetOperations<String, Long> ops = longRedisTemplate.opsForSet();
        ops.add(setKey, value);
    }

    public Set<Long> setMembers(String setKey) {
        SetOperations<String, Long> ops = longRedisTemplate.opsForSet();
        return ops.members(setKey);
    }

    // bitmap operation
    public Boolean bitSet(String key, long offset, boolean flag) {
        ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
        return ops.setBit(key, offset, flag);
    }

    public Boolean bitGet(String key, long offset) {
        ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
        return ops.getBit(key, offset);
    }

    public Long bitCount(String key) {
        return stringRedisTemplate.execute((RedisCallback<Long>) redisConnection -> redisConnection.bitCount(key.getBytes(StandardCharsets.UTF_8)));
    }

    // Hash K/V String
    public void hSet(String key, String field, String value) {
        HashOperations<String, String, String> ops = stringRedisTemplate.opsForHash();
        ops.put(key, field, value);
    }

    public String hGet(String key, String field) {
        HashOperations<String, String, String> ops = stringRedisTemplate.opsForHash();
        return ops.get(key, field);
    }

    public Set<String> hKeys(String key) {
        HashOperations<String, String, String> ops = stringRedisTemplate.opsForHash();
        return ops.keys(key);
    }

    public Boolean hExists(String key, String field) {
        HashOperations<String, String, String> ops = stringRedisTemplate.opsForHash();
        return ops.hasKey(key, field);
    }

    // File K byte V operation
    public void setFileCache(String key, byte[] value) {
        ValueOperations<String, byte[]> ops = redisTemplateOfFileCache.opsForValue();
        ops.set(key, value);
    }

    public byte[] getFileCache(String key) {
        ValueOperations<String, byte[]> ops = redisTemplateOfFileCache.opsForValue();
        return ops.get(key);
    }

    public void setFileCache(String key, String hashKey, byte[] value) {
        HashOperations<String, String, byte[]> ops = redisTemplateOfFileCache.opsForHash();
        ops.put(key, hashKey, value);
    }

    public byte[] getFileCache(String key, String hashKey) {
        HashOperations<String, String, byte[]> ops = redisTemplateOfFileCache.opsForHash();
        return ops.get(key, hashKey);
    }

    public Boolean cacheKeyExists(String key) {
        return redisTemplateOfFileCache.hasKey(key);
    }

    public Boolean cacheKeyExists(String key, String member) {
        return redisTemplateOfFileCache.opsForHash().hasKey(key, member);
    }

    public void removeFileCache(String key) {
        redisTemplateOfFileCache.delete(key);
    }
}